#include <mysql/mysql.h>
#include <openssl/evp.h>
#include <sstream>
#include <iomanip>
#include "mysql_util.hpp"
#include <openssl/sha.h>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <stdexcept>

    const std::string oj_questions = "oj_questions";
    const std::string host = "43.139.165.163";
    const std::string user = "oj_client";
    const std::string passwd = "123456";
    const std::string db = "oj";
    const int port = 3306;


MySQLUtil::MySQLUtil(const std::string& host, const std::string& user,const std::string& passwd,const std::string& db,unsigned int port)
{
    conn = mysql_init(nullptr);
    if (!conn) {    
        throw std::runtime_error("mysql_init failed");
    }

    if (nullptr == mysql_real_connect(conn, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0)) {
        throw std::runtime_error("mysql_real_connect failed: " + std::string(mysql_error(conn)));
    }
    mysql_set_character_set(conn, "utf8mb4");
}

MySQLUtil::~MySQLUtil() {
    if (conn) mysql_close(conn);
}

std::string MySQLUtil::GenerateSalt() {
    static const char* chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    std::string salt;
    srand(time(nullptr) + rand());
    for (int i = 0; i < 32; ++i) {
        salt += chars[rand() % (sizeof(chars) - 1)];
    }
    return salt;
}

// std::string MySQLUtil::SHA256(const std::string& str) {
//     unsigned char hash[SHA256_DIGEST_LENGTH];
//     SHA256_CTX sha256;
//     SHA256_Init(&sha256);
//     SHA256_Update(&sha256, str.c_str(), str.size());
//     SHA256_Final(hash, &sha256);
//     char buf[2 * SHA256_DIGEST_LENGTH + 1];
//     for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
//         sprintf(buf + 2*i, "%02x", hash[i]);
//     }
//     buf[2 * SHA256_DIGEST_LENGTH] = 0;
//     return std::string(buf);
// }
 std::string MySQLUtil::SHA256(const std::string& str) 
{ 
        EVP_MD_CTX* ctx = EVP_MD_CTX_new();  // 创建新的上下文
        if (ctx == nullptr) {
            return "";  // 错误处理
        }

        // 初始化 SHA256 算法
        if (EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr) != 1) {
            EVP_MD_CTX_free(ctx);
            return "";
        }

        // 更新数据
        if (EVP_DigestUpdate(ctx, str.c_str(), str.size()) != 1) {
            EVP_MD_CTX_free(ctx);
            return "";
        }

        unsigned char hash[EVP_MAX_MD_SIZE];
        unsigned int len = 0;
        // 计算最终哈希值
        if (EVP_DigestFinal_ex(ctx, hash, &len) != 1) {
            EVP_MD_CTX_free(ctx);
            return "";
        }

        EVP_MD_CTX_free(ctx);  // 释放上下文

        // 转换为十六进制字符串
        std::stringstream ss;
        for (unsigned int i = 0; i < len; ++i) {
            ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(hash[i]);
        }
        return ss.str();
    
}

bool MySQLUtil::RegisterUser(const std::string& username, const std::string& password) {
    // 检查用户名是否存在
    std::string check_sql = "SELECT id FROM oj_user WHERE username = '" + username + "' LIMIT 1";
    if (mysql_query(conn, check_sql.c_str()) != 0) {
        throw std::runtime_error("mysql_query failed: " + std::string(mysql_error(conn)));
    }
    MYSQL_RES* res = mysql_store_result(conn);
    if (res && mysql_num_rows(res) > 0) {
        mysql_free_result(res);
        return false; // 用户名已存在
    }
    if (res) mysql_free_result(res);

    // 生成盐值和加密密码
    std::string salt = GenerateSalt();
    std::string encrypted_pwd = SHA256(password + salt);

    // 插入新用户
    std::string insert_sql = "INSERT INTO oj_user (username, password, salt) VALUES ('"
                           + username + "', '" + encrypted_pwd + "', '" + salt + "')";
    if (mysql_query(conn, insert_sql.c_str()) != 0) {
        throw std::runtime_error("mysql_query failed: " + std::string(mysql_error(conn)));
    }
    return true;
}